package com.fanrenqiji.modules.sys.service.impl;

import com.fanrenqiji.common.persistence.Page;
import com.fanrenqiji.common.security.Digests;
import com.fanrenqiji.common.service.BaseCommonService;
import com.fanrenqiji.common.utils.StringUtils;
import com.fanrenqiji.common.utils.SystemAuthorizingCacheUtils;
import com.fanrenqiji.modules.sys.dao.MenuDao;
import com.fanrenqiji.modules.sys.dao.OfficeDao;
import com.fanrenqiji.modules.sys.dao.RoleDao;
import com.fanrenqiji.modules.sys.dao.UserDao;
import com.fanrenqiji.modules.sys.entity.Menu;
import com.fanrenqiji.modules.sys.entity.Office;
import com.fanrenqiji.modules.sys.entity.Role;
import com.fanrenqiji.modules.sys.entity.User;
import com.fanrenqiji.modules.sys.security.SystemAuthorizingRealm;
import com.fanrenqiji.modules.sys.service.SystemService;
import com.fanrenqiji.modules.sys.utils.UserUtils;
import org.apache.shiro.SecurityUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author lijian E-mail:ljz0721cx@163.com
 * @version 创建时间：2015年1月21日 下午12:44:24
 * @description
 */
@Service(value = "systemService")
@Transactional(readOnly = true)
public class SystemCommonServiceImpl extends BaseCommonService implements SystemService {

	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MenuDao menuDao;
	@Autowired
	private OfficeDao officeDao;
	@Autowired
	private SystemAuthorizingRealm systemRealm;

	/**
	 * 通过ID获得用户
	 */
	@Override
	public User getUser(Long id) {
		return userDao.findOne(id);
	}

	/**
	 * 通过登录名获得用户
	 */
	@Override
	public User getUserByLoginName(String username) {
		return userDao.findUserByLoginName(username);
	}

	public List<User> findAllUser() {
		DetachedCriteria dc = userDao.createDetachedCriteria();
		dc.add(Restrictions.eq("userState", "ACTIVE"));
		dc.add(Restrictions.eq(User.DEL_FLAG, User.DEL_FLAG_NORMAL));
		return userDao.find(dc);
	}

	/**
	 * 修改登陆的Ip地址
	 */
	@Transactional(readOnly = false)
	public void updateUserLoginInfo(Long id) {
		userDao.updateLoginInfo(SecurityUtils.getSubject().getSession()
				.getHost(), new Date(), id);
	}

	/**
	 * 保存用户
	 */
	@Override
	@Transactional(readOnly = false)
	public void saveUser(User user) {
		// 清除缓存数据
		userDao.clear();
		userDao.save(user);
		// 清空所有关联认证
		systemRealm.clearAllCachedAuthorizationInfo();
	}

	/**
	 * 修改后清理用户的缓存和认证，从新登陆系统 修改当前登陆用户密码
	 */
	@Override
	@Transactional(readOnly = false)
	public void updatePasswordById(Long id, String loginName, String newPassword) {
		userDao.updatePasswordById(Digests.entryptPassword(newPassword), id);
		systemRealm.clearCachedAuthorizationInfo(loginName);
	}

	/**
	 * 获得用户的分页数据
	 * 
	 * @param page
	 *            分页对象
	 * @param user
	 *            要管理的用户
	 * @return
	 */
	public Page<User> findUserByPage(Page<User> page, User user) {
		DetachedCriteria dc = userDao.createDetachedCriteria();
		User currentUser = UserUtils.getUser();
		// 创建company的Alias
		dc.createAlias("company", "company");
		if (user.getCompany() != null && user.getCompany().getId() != null) {
			dc.add(Restrictions.or(
					Restrictions.eq("company.id", user.getCompany().getId()),
					Restrictions.like("company.parentIds", "%,"
							+ user.getCompany().getId() + ",%")));
		}
		// 创建office的alias
		dc.createAlias("office", "office");
		if (user.getOffice() != null && user.getOffice().getId() != null) {
			dc.add(Restrictions.or(
					Restrictions.eq("office.id", user.getOffice().getId()),
					Restrictions.like("office.parentIds", "%,"
							+ user.getOffice().getId() + ",%")));
		}
		// 如果不是超级管理员，则不显示超级管理员用户
		if (!currentUser.isAdmin()) {
			dc.add(Restrictions.ne("id", 1L));
		}
		// 添加数据范围过滤
		dc.add(dataScopeFilter(currentUser, "office", ""));
		// 一下是相关的查询条件
		if (StringUtils.isNotEmpty(user.getLoginName())) {
			dc.add(Restrictions.like("loginName", "%" + user.getLoginName()
					+ "%"));
		}
		if (StringUtils.isNotEmpty(user.getName())) {
			dc.add(Restrictions.like("name", "%" + user.getName() + "%"));
		}

		if (StringUtils.isNotEmpty(user.getUserState())) {
			dc.add(Restrictions.eq("userState", user.getUserState()));
		}

		dc.add(Restrictions.eq(User.DEL_FLAG, User.DEL_FLAG_NORMAL));
		if (!StringUtils.isNotEmpty(page.getOrderBy())) {
			dc.addOrder(Order.asc("company.code"))
					.addOrder(Order.asc("office.code"))
					.addOrder(Order.desc("id"));
		}
		return userDao.find(page, dc);
	}

	/************************* RoleService **********************/
	/**
	 * 通过角色id找到对应的角色
	 */
	@Override
	public Role getRole(Long id) {
		return roleDao.findOne(id);
	}

	/**
	 * 获得当前登陆用户的角色
	 */
	@Override
	public List<Role> findAllRole() {
		User user = UserUtils.getUser();
		DetachedCriteria dc = roleDao.createDetachedCriteria();
		dc.createAlias("office", "office");
		// 添加数据权限
		if (!user.isAdmin()) {
			if(user.getRoleIdList().contains(9l)) {
				dc.add(dataScopeFilter(user, "office", "")
						.add(Restrictions.eq("roleType", "company")));
			}else{
				dc.add(dataScopeFilter(user, "office", ""));
			}
		} else {
			dc.add(dataScopeFilter(user, "office", ""));
		}
		dc.add(Restrictions.eq(Role.DEL_FLAG, Role.DEL_FLAG_NORMAL));
		dc.addOrder(Order.asc("office.code")).addOrder(Order.asc("name"));
		return roleDao.find(dc);
	}

	/**
	 * 通过角色名获得有效的角色
	 */
	@Override
	public Role findRoleByName(String name) {
		return roleDao.findByName(name);
	}

	/**
	 * 添加或跟新角色
	 */
	@Override
	@Transactional(readOnly = false)
	public void saveRole(Role role) {
		roleDao.clear();
		roleDao.save(role);
	}

	/**
	 * 将用户从角色中移除
	 */
	@Override
	@Transactional(readOnly = false)
	public Boolean outUserInRole(Role role, Long userId) {
		User user = userDao.findOne(userId);
		List<Long> roleIds = user.getRoleIdList();
		List<Role> roles = user.getRoleList();
		//
		if (roleIds.contains(role.getId())) {
			roles.remove(role);
			saveUser(user);
			return true;
		}
		return false;
	}

	/**
	 * 添加用户到角色中
	 */
	@Override
	@Transactional(readOnly = false)
	public User assignUserToRole(Role role, Long userId) {
		User user = userDao.findOne(userId);
		List<Long> roleIds = user.getRoleIdList();
		if (roleIds.contains(role.getId())) {
			return null;
		}
		user.getRoleList().add(role);
		saveUser(user);
		return user;
	}

	/************************* MenuService **********************/

	/**
	 * 根据Id获得菜单项
	 */
	@Override
	public Menu getMenu(Long id) {
		return menuDao.findOne(id);
	}

	/**
	 * 获得登陆用户当前的所有的菜单
	 */
	@Override
	public List<Menu> findAllMenu() {
		return UserUtils.getMenuList();
	}

	/**
	 * 添加相应的菜单
	 */
	@Override
	@Transactional(readOnly = false)
	public void saveMenu(Menu menu) {
		menu.setParent(this.getMenu(menu.getParent().getId()));
		// 获取修改前的parentIds，用于更新子节点的parentIds
		String oldParentIds = menu.getParentIds();
		menu.setParentIds(menu.getParent().getParentIds()
				+ menu.getParent().getId() + ",");
		menuDao.clear();
		menuDao.save(menu);
		// 更新子节点 parentIds
		List<Menu> list = menuDao.findByParentIdsContaining("," + menu.getId()
				+ ",");
		for (Menu e : list) {
			e.setParentIds(e.getParentIds().replace(oldParentIds,
					menu.getParentIds()));
		}
		menuDao.save(list);
		systemRealm.clearAllCachedAuthorizationInfo();
		SystemAuthorizingCacheUtils.removeCache(UserUtils.CACHE_MENU_LIST);
	}

	/**
	 * 通过id删除所有的菜单项
	 */
	@Override
	@Transactional(readOnly = false)
	public void deleteMenu(Long id) {
		menuDao.deleteById(id, "%," + id + ",%");
		systemRealm.clearAllCachedAuthorizationInfo();
		SystemAuthorizingCacheUtils.removeCache(UserUtils.CACHE_MENU_LIST);
	}

	@Override
	@Transactional(readOnly = false)
	public List<User> findUserByRole(Role role) {
		User user = UserUtils.getUser();
		DetachedCriteria dc = userDao.createDetachedCriteria();
		dc.createAlias("roleList", "role");
		dc.createAlias("office", "office");
		dc.add(dataScopeFilter(user, "office", ""));
		dc.add(Restrictions.eq("role.id", role.getId()));
		return userDao.find(dc);
	}

	/**
	 * 查询已经存在的用户
	 */
	@Override
	public User findByLoginName(String username) {
		return userDao.findByLoginName(username);
	}

	@Override
	public List<User> findUserByOffice(Office office) {
		return userDao.findUserByOffice(office);
	}

	@Override
	public Page<User> findOfficeBelowUserByPage(Page<User> page, User user) {
		DetachedCriteria dc = userDao.createDetachedCriteria();

		if (user.getOffice() != null && user.getOffice().getId() != null) {
			// 创建office的alias
			dc.createAlias("office", "office");
			dc.add(Restrictions.eq("office.id", user.getOffice().getId()));
		}
		// 一下是相关的查询条件
		if (StringUtils.isNotEmpty(user.getLoginName())) {
			dc.add(Restrictions.like("loginName", "%" + user.getLoginName()
					+ "%"));
		}
		if (StringUtils.isNotEmpty(user.getName())) {
			dc.add(Restrictions.like("name", "%" + user.getName() + "%"));
		}

		dc.add(Restrictions.eq(User.DEL_FLAG, User.DEL_FLAG_NORMAL));
		if (!StringUtils.isNotEmpty(page.getOrderBy())) {
			dc.addOrder(Order.asc("id"));
		}
		return userDao.find(page, dc);
	}

	/*
	 * 查找机构下是否存在用户
	 */
	@Override
	public Long findOfficeBelowIsExistUser(Long officeId) {
		DetachedCriteria dc = userDao.createDetachedCriteria();

		// 创建office的alias
		dc.createAlias("office", "office");
		dc.add(Restrictions.eq("office.id", officeId));

		dc.add(Restrictions.eq(User.DEL_FLAG, User.DEL_FLAG_NORMAL));

		return userDao.count(dc);
	}

}
